home *** CD-ROM | disk | FTP | other *** search
/ L' Effet Pommier 3 / L'Effet Pommier - Volume 03.iso / Programmation / gray image 2.1 / vfilter.cc < prev    next >
Text File  |  1995-05-03  |  15KB  |  415 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *          Verify image filtration and related functions
  8.  *
  9.  * $Id: vfilter.cc,v 2.0 1995/03/18 18:19:06 oleg Exp oleg $
  10.  *
  11.  ************************************************************************
  12.  */
  13.  
  14. #include "filter.h"
  15. #include <iostream.h>
  16.  
  17. static IMAGE Test_image(16,31,8); //(256,512,8);
  18.  
  19. /*
  20.  *----------------------------------------------------------------------
  21.  *        Make sure that Test_image is what we've expected
  22.  */
  23.  
  24. static void verify_identity(const IMAGE& test_image, const IMAGE& ethalon)
  25. {
  26.   if( test_image == ethalon )
  27.     return;
  28.   compare(test_image,ethalon,"test image is different from ethalon");
  29.   test_image.print("Test image");
  30.   ethalon.print("ethalon");
  31.   _error("Something fishy is going on here... look into this...");
  32. }
  33.  
  34. /*
  35.  *----------------------------------------------------------------------
  36.  *            Testing convolutions
  37.  */
  38. static void test_convolutions(void)
  39. {
  40.   cout << "\nVerify convolutions of an image" << endl;
  41.  
  42.   const int seed = 137;
  43.  
  44.   IMAGE expected(Test_image);
  45.  
  46.   {
  47.     cout << "\thomogenious image should stay the same (or similar)" << endl;
  48.     Test_image = seed;
  49.     verify_pixel_value(FilterIt(Test_image).
  50.                conv(conv_kernel(1,2,3),FilterIt::Rows),
  51.                (1+2+3)*seed);
  52.     verify_pixel_value(FilterIt(Test_image=seed).
  53.                conv(conv_kernel(1,2,3),FilterIt::Columns),
  54.                (1+2+3)*seed);
  55.     verify_pixel_value(FilterIt(Test_image=seed).
  56.                conv(conv_kernel(1,2,3)),
  57.                (1+2+3)*(1+2+3)*seed);
  58.  
  59.     verify_pixel_value(FilterIt(Test_image=seed).
  60.                conv_row(conv_kernel(1,2,1,over_2_up(2))),
  61.                seed);
  62.     verify_pixel_value(FilterIt(Test_image=seed).
  63.                conv_col(conv_kernel(4,8,4,over_2_up(3))),
  64.                2*seed);
  65.     verify_pixel_value(FilterIt(Test_image=seed).
  66.                conv(conv_kernel(0,2,6,CommonDenom(2)),FilterIt::Rows),
  67.                4*seed);
  68.     verify_pixel_value(FilterIt(Test_image=seed).
  69.                conv(conv_kernel(1,2,3,CommonDenom(6))),
  70.                seed);
  71.   }
  72.  
  73.   {
  74.     cout << "\tTest filtering a single vertical line" << endl;
  75.     IMAGE vert_line(Test_image);
  76.     vert_line = 0;
  77.     vert_line.rectangle(rowcol(0,vert_line.q_ncols()/2),
  78.             rowcol(vert_line.q_nrows()-1,
  79.                    vert_line.q_ncols()/2)) = -seed;
  80.     Test_image = vert_line;
  81.     verify_identity(FilterIt(Test_image).
  82.             conv(conv_kernel(1,2,1),FilterIt::Columns)>>=2,vert_line);
  83.     verify_identity(FilterIt(Test_image).
  84.             conv_col(conv_kernel(1,2,3,CommonDenom(6))),vert_line);
  85.     verify_identity(FilterIt(Test_image).
  86.             conv(conv_kernel(0,2,0,over_2_up(1))),vert_line);
  87.     expected = 0;
  88.     expected.rectangle(rowcol(0,vert_line.q_ncols()/2-1),
  89.             rowcol(vert_line.q_nrows()-1,
  90.                    vert_line.q_ncols()/2+1)) = -seed;
  91.     verify_identity(FilterIt(Test_image=vert_line).
  92.             conv(conv_kernel(1,1,1),FilterIt::Rows),expected);
  93.   }
  94.  
  95.   {
  96.     cout << "\tTest filtering a single horizontal line" << endl;
  97.     IMAGE hor_line(Test_image);
  98.     hor_line = 1;
  99.     hor_line.rectangle(rowcol(hor_line.q_nrows()/2-1,0),
  100.                rowcol(hor_line.q_nrows()/2-1,
  101.                   hor_line.q_ncols()-1)) = seed;
  102.     Test_image = hor_line;
  103.     verify_identity(FilterIt(Test_image).
  104.             conv(conv_kernel(1,2,1,over_2_up(2)),FilterIt::Rows),
  105.             hor_line);
  106.     verify_identity(FilterIt(Test_image).
  107.             conv_row(conv_kernel(3,2,1,CommonDenom(6))),hor_line);
  108.     verify_identity(FilterIt(Test_image).
  109.             conv(conv_kernel(0,3,0,CommonDenom(3))),hor_line);
  110.     Test_image = hor_line;
  111.     expected = hor_line(0,0);
  112.     expected.rectangle(rowcol(hor_line.q_nrows()/2-2,0),
  113.                rowcol(hor_line.q_nrows()/2-2,
  114.                   hor_line.q_ncols()-1)) = (3*seed+3)/6;
  115.     expected.rectangle(rowcol(hor_line.q_nrows()/2-1,0),
  116.                rowcol(hor_line.q_nrows()/2-1,
  117.                   hor_line.q_ncols()-1)) = (2*seed+4)/6;
  118.     expected.rectangle(rowcol(hor_line.q_nrows()/2,0),
  119.                rowcol(hor_line.q_nrows()/2,
  120.                   hor_line.q_ncols()-1)) = (seed+5)/6;
  121.     verify_identity(FilterIt(Test_image=hor_line).
  122.             conv(conv_kernel(1,2,3,CommonDenom(6)),FilterIt::Columns),
  123.             expected);
  124.   }
  125.  
  126.   {
  127.     cout << "\tTest filtering (phase shifting) a small 2x2 square" << endl;
  128.     const card sq_row = Test_image.q_nrows()/3;
  129.     const card sq_col = (2*Test_image.q_ncols())/3;
  130.     IMAGE small_sq(Test_image);
  131.     small_sq = 1;
  132.     small_sq(sq_row,sq_col) = seed; small_sq(sq_row,sq_col+1) = seed+1;
  133.     small_sq(sq_row+1,sq_col) = seed+1; small_sq(sq_row+1,sq_col+1) = seed;
  134.  
  135.     verify_identity(FilterIt(Test_image=small_sq).
  136.             conv(conv_kernel(0,1,0)),small_sq);
  137.     expected = small_sq; expected >>=2;
  138.     verify_identity(FilterIt(Test_image).
  139.             conv(conv_kernel(0,2,0,CommonDenom(4))),expected);
  140.  
  141.     expected = small_sq(0,0);
  142.     expected.square_of(2,rowcol(sq_row+1,sq_col+1)) =
  143.       small_sq.square_of(2,rowcol(sq_row,sq_col));
  144.     verify_identity(FilterIt(Test_image=small_sq).
  145.             conv(conv_kernel(1,0,0)),expected);
  146.  
  147.     expected = small_sq(0,0);
  148.     expected.square_of(2,rowcol(sq_row-1,sq_col-1)) =
  149.       small_sq.square_of(2,rowcol(sq_row,sq_col));
  150.     verify_identity(FilterIt(Test_image=small_sq).
  151.             conv(conv_kernel(0,0,2,over_2_up(1))),expected);
  152.   }
  153.  
  154.   cout << "\nDone" << endl;
  155. }
  156.  
  157. /*
  158.  *----------------------------------------------------------------------
  159.  *            Testing median filtration
  160.  */
  161.  
  162. static void test_median_filtration(void)
  163. {
  164.   cout << "\nVerify median filtration of an image" << endl;
  165.  
  166.   const int seed = 141;
  167.  
  168.   IMAGE expected(Test_image);
  169.  
  170.   cout << "\thomogenious image should stay the same" << endl;
  171.   Test_image = seed; expected = Test_image;
  172.   verify_identity(FilterIt(Test_image).median(FilterIt::RowsAndColumns),
  173.           expected);
  174.   verify_identity(FilterIt(Test_image).median(FilterIt::RowsAndColumns,5),
  175.           expected);
  176.   
  177.   cout << "\t1-pixel speckle should be filtered out" << endl;
  178.   Test_image = seed; Test_image(4,4) = 0;
  179.   verify_pixel_value(FilterIt(Test_image).median(FilterIt::Rows),seed);
  180.   Test_image(4,4) = 0;
  181.   verify_pixel_value(FilterIt(Test_image).median(FilterIt::Columns),seed);
  182.   Test_image(4,4) = 0;
  183.   verify_pixel_value(FilterIt(Test_image).median(FilterIt::Rows,5),seed);
  184.   Test_image(4,4) = 0;
  185.   verify_pixel_value(FilterIt(Test_image).median(FilterIt::Columns,5),seed);
  186.   Test_image(4,4) = 0; Test_image ^= (~0);
  187.   expected = Test_image; expected(4,4) = expected(0,0);
  188.   verify_pixel_value(FilterIt(Test_image).median(FilterIt::Columns),seed ^ ~0);
  189.   Test_image = seed; Test_image(4,4) = 0; Test_image ^= (~0);
  190.   verify_pixel_value(FilterIt(Test_image).median(FilterIt::Columns,5),
  191.              seed ^ ~0);
  192.   
  193.   {
  194.     cout << "\tTest filtering a single vertical line" << endl;
  195.     IMAGE vert_line(Test_image);
  196.     vert_line = 0;
  197.     vert_line.rectangle(rowcol(0,vert_line.q_ncols()/2),
  198.             rowcol(vert_line.q_nrows()-1,
  199.                    vert_line.q_ncols()/2)) = -seed;
  200.     Test_image = vert_line;
  201.     verify_identity(FilterIt(Test_image).median(FilterIt::Columns),vert_line);
  202.     verify_identity(FilterIt(Test_image).median(FilterIt::Columns,5),
  203.             vert_line);
  204.     Test_image = vert_line;
  205.     expected = vert_line(0,0);
  206.     verify_identity(FilterIt(Test_image).median(FilterIt::Rows,3),expected);
  207.     Test_image = vert_line;
  208.     verify_identity(FilterIt(Test_image).median(FilterIt::Rows,5),expected);
  209.   }
  210.  
  211.   {
  212.     cout << "\tTest filtering a single horizontal line" << endl;
  213.     IMAGE hor_line(Test_image);
  214.     hor_line = ~0;
  215.     hor_line.rectangle(rowcol(hor_line.q_nrows()/2-1,0),
  216.                rowcol(hor_line.q_nrows()/2-1,
  217.                   hor_line.q_ncols()-1)) = seed;
  218.     Test_image = hor_line;
  219.     verify_identity(FilterIt(Test_image).median(FilterIt::Rows),hor_line);
  220.     verify_identity(FilterIt(Test_image).median(FilterIt::Rows,5),hor_line);
  221.     Test_image = hor_line;
  222.     expected = hor_line(0,0);
  223.     verify_pixel_value(FilterIt(Test_image).median(FilterIt::Columns,3),
  224.                hor_line(0,0));
  225.     Test_image = hor_line;
  226.     verify_identity(FilterIt(Test_image).median(FilterIt::Columns,5),expected);
  227.   }
  228.  
  229.   {
  230.     cout << "\tBorder outlines should stay the same" << endl;
  231.     const int nrows = Test_image.q_nrows();
  232.     const int ncols = Test_image.q_ncols();
  233.     Test_image = 0;
  234.     Test_image.rectangle(rowcol(0,0),rowcol(nrows-1,0)) = seed;
  235.     Test_image.rectangle(rowcol(1,1),rowcol(nrows-2,1)) = seed-1;
  236.     Test_image.rectangle(rowcol(0,ncols-1),rowcol(nrows-1,ncols-1)) = seed;
  237.     Test_image.rectangle(rowcol(1,ncols-2),rowcol(nrows-2,ncols-2)) = seed-1;
  238.     Test_image.rectangle(rowcol(0,0),rowcol(0,ncols-1)) = seed;
  239.     Test_image.rectangle(rowcol(1,1),rowcol(1,ncols-2)) = seed-1;
  240.     Test_image.rectangle(rowcol(nrows-1,0),rowcol(nrows-1,ncols-1)) = seed;
  241.     Test_image.rectangle(rowcol(nrows-2,1),rowcol(nrows-2,ncols-2)) = seed-1;
  242.     expected = Test_image;
  243.     verify_identity(FilterIt(Test_image).median(FilterIt::RowsAndColumns,3),
  244.             expected);
  245.     verify_identity(FilterIt(Test_image).median(FilterIt::RowsAndColumns,5),
  246.             expected);
  247.   }
  248.  
  249.   {
  250.     cout << "\tTest filtering a small 2x2 square" << endl;
  251.     const card sq_row = Test_image.q_nrows()/3;
  252.     const card sq_col = (2*Test_image.q_ncols())/3;
  253.     IMAGE small_sq(Test_image);
  254.     small_sq = 1;
  255.     small_sq(sq_row,sq_col) = seed; small_sq(sq_row,sq_col+1) = seed+1;
  256.     small_sq(sq_row+1,sq_col) = seed+1; small_sq(sq_row+1,sq_col+1) = seed;
  257.     expected = small_sq; expected.square_of(2,rowcol(sq_row,sq_col)) = seed;
  258.  
  259.     verify_identity(FilterIt(Test_image=small_sq).median(FilterIt::Columns,3),
  260.             expected);
  261.     verify_identity(FilterIt(Test_image=small_sq).median(FilterIt::Rows,3),
  262.             expected);
  263.     verify_identity(FilterIt(Test_image=small_sq).
  264.             median(FilterIt::RowsAndColumns,3),expected);
  265.     verify_pixel_value(FilterIt(Test_image=small_sq).
  266.                median(FilterIt::Columns,5),expected(0,0));
  267.     verify_pixel_value(FilterIt(Test_image=small_sq).
  268.                median(FilterIt::Rows,5),expected(0,0));
  269.     verify_pixel_value(FilterIt(Test_image=small_sq).
  270.                median(FilterIt::RowsAndColumns,5),expected(0,0));
  271.   }
  272.  
  273.   {
  274.     cout << "\tTest filtering a bigger 4x4 square" << endl;
  275.     const card sq_row = (2*Test_image.q_nrows())/3;
  276.     const card sq_col = Test_image.q_ncols()/3;
  277.     IMAGE med_sq(Test_image);
  278.     med_sq = seed;
  279.     med_sq.square_of(4,rowcol(sq_row,sq_col)) = 1;
  280.     med_sq(sq_row,sq_col+2) = 2;
  281.     verify_identity(FilterIt(Test_image=med_sq).median(FilterIt::Columns,3),
  282.             med_sq);
  283.     expected = med_sq; expected(sq_row,sq_col+2) = 1;
  284.     expected(sq_row,sq_col+3) = 2;
  285.     verify_identity(FilterIt(Test_image=med_sq).median(FilterIt::Rows,3),
  286.             expected);
  287.     verify_identity(FilterIt(Test_image=med_sq).
  288.             median(FilterIt::RowsAndColumns,3),expected);
  289.     verify_identity(FilterIt(Test_image=med_sq).median(FilterIt::Columns,5),
  290.             med_sq);
  291.     expected = med_sq;
  292.     expected(sq_row,sq_col+2) = 1;
  293.     expected(sq_row,sq_col) = 2; expected(sq_row,sq_col+3) = 2;
  294.     verify_identity(FilterIt(Test_image=med_sq).median(FilterIt::Rows,5),
  295.             expected);
  296.     verify_identity(FilterIt(Test_image=med_sq).
  297.             median(FilterIt::RowsAndColumns,5),expected);
  298.   }
  299.  
  300.   cout << "\nDone\n";
  301. }
  302.  
  303. /*
  304.  *------------------------------------------------------------------------
  305.  *            Testing table look-ups
  306.  */
  307.  
  308. static void test_lookups(void)
  309. {
  310.   cout << "\nVerify table lookups" << endl;
  311.  
  312.   const int min_seed = -2;
  313.  
  314.   IMAGE diverse_image(Test_image);    // With all values -2:no_pixels
  315.   {
  316.     class MakeDiverse : public PixelPrimAction
  317.     {
  318.       GRAY_SIGNED curr;
  319.       void operation(GRAY& pixel) { pixel = curr++; }
  320.       public: MakeDiverse(const GRAY_SIGNED seed) : curr(seed) {}
  321.     };
  322.     diverse_image.apply(MakeDiverse(min_seed));
  323.   }
  324.  
  325.   IMAGE expected(Test_image);
  326.  
  327.   LookupT Identical(LookupT::Identical(Test_image.q_depth()));
  328.  
  329.   {
  330.     cout << "\ttest applying identical LookupT" << endl;
  331.     verify_identity(FilterIt(Test_image=diverse_image).
  332.             translate(Identical,LookupT::LeaveFringes),
  333.             diverse_image);
  334.  
  335.     LookupT another_identical(Identical);
  336.     another_identical.apply(Identical,LookupT::LeaveFringes);
  337.     verify_identity(FilterIt(Test_image=diverse_image).
  338.             translate(another_identical,LookupT::LeaveFringes),
  339.             diverse_image);
  340.  
  341.     another_identical.apply(Identical,LookupT::CoerceFringes);
  342.     verify_identity(FilterIt(Test_image=diverse_image).
  343.             translate(another_identical,LookupT::LeaveFringes),
  344.             diverse_image);
  345.  
  346.     cout << "\tCoercing during translation should be the same as "
  347.             "clip_to_intensity_range()" << endl;
  348.     assert( !(diverse_image >= 0) );        // Make sure we have smth to
  349.     assert( !(diverse_image < (1<<diverse_image.q_depth())) );    // clip from
  350.     (expected = diverse_image).clip_to_intensity_range();
  351.     
  352.     verify_identity(FilterIt(Test_image).
  353.             translate(Identical,LookupT::CoerceFringes),
  354.             expected);
  355.   }
  356.  
  357.   {
  358.     cout << "\ttest applying one pixel mapping LookupT" << endl;
  359.     const GRAY seed = 4;
  360.     assert( !(diverse_image != seed) );        // make sure we have this pixel
  361.     LookupT map(LookupT::MapTo(seed,seed+1));
  362.     assert( FilterIt(Test_image=diverse_image).
  363.       translate(map,LookupT::LeaveFringes) != seed );
  364.  
  365. //    const GRAY seed1 = -2;
  366.     const GRAY seed1 = diverse_image.q_npixels()-2-1;
  367.     assert( !(diverse_image != seed1) );    // make sure we have this pixel
  368.     assert( diverse_image != seed1+1 );
  369.     LookupT map1(LookupT::MapTo(seed1,seed1+1));
  370.     assert( FilterIt(Test_image=diverse_image).
  371.       translate(map1,LookupT::LeaveFringes) != seed1 );
  372.     assert( !(Test_image != seed1+1) );        // Now we have seed-1
  373.  
  374.     cout << "\tCoercing during translation should make all pixels the same"
  375.      << endl;
  376.     verify_pixel_value(FilterIt(Test_image=diverse_image).
  377.             translate(map,LookupT::CoerceFringes),seed+1);
  378.     verify_pixel_value(FilterIt(Test_image=diverse_image).
  379.             translate(map1,LookupT::CoerceFringes),seed1+1);
  380.     map.apply(Identical,LookupT::CoerceFringes);
  381.     verify_pixel_value(FilterIt(Test_image=diverse_image).
  382.             translate(map,LookupT::CoerceFringes),seed+1);
  383.     LookupT another_map = Identical;
  384.     another_map.apply(map,LookupT::CoerceFringes);
  385.     verify_pixel_value(FilterIt(Test_image=diverse_image).
  386.             translate(another_map,LookupT::CoerceFringes),seed+1);
  387.   }
  388.  
  389.   {
  390.     cout << "\ttest inverting an image via LookupT" << endl;
  391.     LookupT invert(Identical);
  392.     for(register GRAY i=invert.q_min(); i<=invert.q_max(); i++)
  393.       invert[i] ^= ((1<<diverse_image.q_depth())-1);
  394.     (expected = diverse_image).clip_to_intensity_range().invert();
  395.     verify_identity(FilterIt(Test_image=diverse_image).
  396.             translate(invert,LookupT::CoerceFringes),
  397.             expected);
  398.   }
  399.     
  400.   cout << "\nDone\n";
  401. }
  402.  
  403.  
  404. /*
  405.  *------------------------------------------------------------------------
  406.  *            The testing routing module
  407.  */
  408.  
  409. main()
  410. {
  411.   test_median_filtration();
  412.   test_convolutions();
  413.   test_lookups();
  414. }
  415.